#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 500010;
const int INF = -1e9;

// 线段树结构体，用于维护区间最大值
struct SegmentTree {
  int max_val[N << 2]; // 线段树数组
  void init() { memset(max_val, -1, sizeof(max_val)); }

  // 更新节点值
  void push_up(int x) {
    max_val[x] = max(max_val[x << 1], max_val[x << 1 | 1]);
  }

  // 单点更新
  // 单点更新函数参数解析
  void update(int x, int pos, int val, int l, int r) {
    // x: 当前线段树节点下标
    // pos: 要更新的原始数组位置(1-based)
    // val: 要更新的值
    // l, r: 当前节点表示的区间范围[l,r]
    if (l == r) {
      max_val[x] = val;
      return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid)
      update(x << 1, pos, val, l, mid);
    else
      update(x << 1 | 1, pos, val, mid + 1, r);

    push_up(x);
  }

  // 区间查询最大值
  // 区间查询函数参数解析
  int query_max(int x, int ql, int qr, int l, int r) {
    // x: 当前线段树节点下标
    // ql, qr: 要查询的区间范围[ql,qr]
    // l, r: 当前节点表示的区间范围[l,r]
    if (ql <= l && r <= qr)
      return max_val[x];
    int mid = (l + r) >> 1;
    int res = INF;
    if (ql <= mid)
      res = max(res, query_max(x << 1, ql, qr, l, mid));
    if (qr > mid)
      res = max(res, query_max(x << 1 | 1, ql, qr, mid + 1, r));
    return res;
  }
};
SegmentTree tree; // 线段树实例
ll height[N], pos[N], dp[N];
// height: 高度数组, pos: 高度对应的位置, dp: 动态规划数组

int main() {
  int n, d, r;
  tree.init();

  cin >> n >> d >> r; // 输入n(位置数), d(最小高度差), r(跳跃范围)

  // 读取高度并记录每个高度的位置
  for (int i = 1; i <= n; i++) {
    cin >> height[i];
    pos[height[i]] = i; // 记录高度对应的位置
  }
  // 注意高度数组是【1, n】的排列
  // 从高到低动态规划(因为要从满足h_pos - h_i >= D的点转移)
  for (int h = n; h >= 1; h--) {
    // 将满足条件的高度(h + d)的dp值加入线段树
    if (h + d <= n)
      tree.update(1, pos[h + d], dp[h + d], 1, n);

    // 查询当前位置左右r范围内的最大dp值
    int left = max(1ll, pos[h] - r);                  // 左边界
    int right = min((ll)n, pos[h] + r);               // 右边界
    dp[h] = 1 + tree.query_max(1, left, right, 1, n); // 转移方程
  }

  // 输出所有位置的最大dp值
  cout << *max_element(dp + 1, dp + 1 + n) << "\n";
  return 0;
}

/*

线段树用于维护区间最大值，支持单点更新和区间查询
动态规划思路是从高到低处理，因为只有高度差≥D的点才能转移
每次处理高度h时，将h+D的dp值加入线段树
查询当前位置±R范围内的最大dp值进行转移
最终结果是所有dp值中的最大值

*/